home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / pcl / src-16f.lha / compiler / sparc / arith.lisp < prev    next >
Encoding:
Text File  |  1992-12-09  |  22.5 KB  |  775 lines

  1. ;;; -*- Package: SPARC -*-
  2. ;;;
  3. ;;; **********************************************************************
  4. ;;; This code was written as part of the Spice Lisp project at
  5. ;;; Carnegie-Mellon University, and has been placed in the public domain.
  6. ;;; If you want to use this code or any part of Spice Lisp, please contact
  7. ;;; Scott Fahlman (FAHLMAN@CMUC). 
  8. ;;; **********************************************************************
  9. ;;;
  10. ;;; $Header: arith.lisp,v 1.9 92/08/02 20:17:04 wlott Exp $
  11. ;;;
  12. ;;;    This file contains the VM definition arithmetic VOPs for the MIPS.
  13. ;;;
  14. ;;; Written by Rob MacLachlan
  15. ;;;
  16. ;;; Converted by William Lott.
  17. ;;; 
  18.  
  19. (in-package "SPARC")
  20.  
  21.  
  22.  
  23. ;;;; Unary operations.
  24.  
  25. (define-vop (fast-safe-arith-op)
  26.   (:policy :fast-safe)
  27.   (:effects)
  28.   (:affected))
  29.  
  30.  
  31. (define-vop (fixnum-unop fast-safe-arith-op)
  32.   (:args (x :scs (any-reg)))
  33.   (:results (res :scs (any-reg)))
  34.   (:note "inline fixnum arithmetic")
  35.   (:arg-types tagged-num)
  36.   (:result-types tagged-num))
  37.  
  38. (define-vop (signed-unop fast-safe-arith-op)
  39.   (:args (x :scs (signed-reg)))
  40.   (:results (res :scs (signed-reg)))
  41.   (:note "inline (signed-byte 32) arithmetic")
  42.   (:arg-types signed-num)
  43.   (:result-types signed-num))
  44.  
  45. (define-vop (fast-negate/fixnum fixnum-unop)
  46.   (:translate %negate)
  47.   (:generator 1
  48.     (inst neg res x)))
  49.  
  50. (define-vop (fast-negate/signed signed-unop)
  51.   (:translate %negate)
  52.   (:generator 2
  53.     (inst neg res x)))
  54.  
  55. (define-vop (fast-lognot/fixnum fixnum-unop)
  56.   (:translate lognot)
  57.   (:generator 2
  58.     (inst xor res x (fixnum -1))))
  59.  
  60. (define-vop (fast-lognot/signed signed-unop)
  61.   (:translate lognot)
  62.   (:generator 1
  63.     (inst not res x)))
  64.  
  65.  
  66.  
  67. ;;;; Binary fixnum operations.
  68.  
  69. ;;; Assume that any constant operand is the second arg...
  70.  
  71. (define-vop (fast-fixnum-binop fast-safe-arith-op)
  72.   (:args (x :target r :scs (any-reg zero))
  73.      (y :target r :scs (any-reg zero)))
  74.   (:arg-types tagged-num tagged-num)
  75.   (:results (r :scs (any-reg)))
  76.   (:result-types tagged-num)
  77.   (:note "inline fixnum arithmetic"))
  78.  
  79. (define-vop (fast-unsigned-binop fast-safe-arith-op)
  80.   (:args (x :target r :scs (unsigned-reg zero))
  81.      (y :target r :scs (unsigned-reg zero)))
  82.   (:arg-types unsigned-num unsigned-num)
  83.   (:results (r :scs (unsigned-reg)))
  84.   (:result-types unsigned-num)
  85.   (:note "inline (unsigned-byte 32) arithmetic"))
  86.  
  87. (define-vop (fast-signed-binop fast-safe-arith-op)
  88.   (:args (x :target r :scs (signed-reg zero))
  89.      (y :target r :scs (signed-reg zero)))
  90.   (:arg-types signed-num signed-num)
  91.   (:results (r :scs (signed-reg)))
  92.   (:result-types signed-num)
  93.   (:note "inline (signed-byte 32) arithmetic"))
  94.  
  95.  
  96. (define-vop (fast-fixnum-binop-c fast-safe-arith-op)
  97.   (:args (x :target r :scs (any-reg zero)))
  98.   (:info y)
  99.   (:arg-types tagged-num
  100.           (:constant (and (signed-byte 11) (not (integer 0 0)))))
  101.   (:results (r :scs (any-reg)))
  102.   (:result-types tagged-num)
  103.   (:note "inline fixnum arithmetic"))
  104.  
  105. (define-vop (fast-unsigned-binop-c fast-safe-arith-op)
  106.   (:args (x :target r :scs (unsigned-reg zero)))
  107.   (:info y)
  108.   (:arg-types unsigned-num
  109.           (:constant (and (signed-byte 13) (not (integer 0 0)))))
  110.   (:results (r :scs (unsigned-reg)))
  111.   (:result-types unsigned-num)
  112.   (:note "inline (unsigned-byte 32) arithmetic"))
  113.  
  114. (define-vop (fast-signed-binop-c fast-safe-arith-op)
  115.   (:args (x :target r :scs (signed-reg zero)))
  116.   (:info y)
  117.   (:arg-types signed-num
  118.           (:constant (and (signed-byte 13) (not (integer 0 0)))))
  119.   (:results (r :scs (signed-reg)))
  120.   (:result-types signed-num)
  121.   (:note "inline (signed-byte 32) arithmetic"))
  122.  
  123.  
  124. (eval-when (compile load eval)
  125.  
  126. (defmacro define-binop (translate untagged-penalty op)
  127.   `(progn
  128.      (define-vop (,(symbolicate "FAST-" translate "/FIXNUM=>FIXNUM")
  129.           fast-fixnum-binop)
  130.        (:translate ,translate)
  131.        (:generator 2
  132.      (inst ,op r x y)))
  133.      (define-vop (,(symbolicate 'fast- translate '-c/fixnum=>fixnum)
  134.           fast-fixnum-binop-c)
  135.        (:translate ,translate)
  136.        (:generator 1
  137.      (inst ,op r x (fixnum y))))
  138.      (define-vop (,(symbolicate "FAST-" translate "/SIGNED=>SIGNED")
  139.           fast-signed-binop)
  140.        (:translate ,translate)
  141.        (:generator ,(1+ untagged-penalty)
  142.      (inst ,op r x y)))
  143.      (define-vop (,(symbolicate 'fast- translate '-c/signed=>signed)
  144.           fast-signed-binop-c)
  145.        (:translate ,translate)
  146.        (:generator ,untagged-penalty
  147.      (inst ,op r x y)))
  148.      (define-vop (,(symbolicate "FAST-" translate "/UNSIGNED=>UNSIGNED")
  149.           fast-unsigned-binop)
  150.        (:translate ,translate)
  151.        (:generator ,(1+ untagged-penalty)
  152.      (inst ,op r x y)))
  153.      (define-vop (,(symbolicate 'fast- translate '-c/unsigned=>unsigned)
  154.           fast-unsigned-binop-c)
  155.        (:translate ,translate)
  156.        (:generator ,untagged-penalty
  157.      (inst ,op r x y)))))
  158.  
  159. ); eval-when
  160.  
  161. (define-binop + 4 add)
  162. (define-binop - 4 sub)
  163. (define-binop logand 2 and)
  164. (define-binop logandc2 2 andn)
  165. (define-binop logior 2 or)
  166. (define-binop logorc2 2 orn)
  167. (define-binop logxor 2 xor)
  168. (define-binop logeqv 2 xnor)
  169.  
  170. ;;; Special case fixnum + and - that trap on overflow.  Useful when we
  171. ;;; don't know that the output type is a fixnum.
  172.  
  173. (define-vop (+/fixnum fast-+/fixnum=>fixnum)
  174.   (:policy :safe)
  175.   (:results (r :scs (any-reg descriptor-reg)))
  176.   (:result-types tagged-num)
  177.   (:note "safe inline fixnum arithmetic")
  178.   (:generator 4
  179.     (inst taddcctv r x y)))
  180.  
  181. (define-vop (+-c/fixnum fast-+-c/fixnum=>fixnum)
  182.   (:policy :safe)
  183.   (:results (r :scs (any-reg descriptor-reg)))
  184.   (:result-types tagged-num)
  185.   (:note "safe inline fixnum arithmetic")
  186.   (:generator 3
  187.     (inst taddcctv r x (fixnum y))))
  188.  
  189. (define-vop (-/fixnum fast--/fixnum=>fixnum)
  190.   (:policy :safe)
  191.   (:results (r :scs (any-reg descriptor-reg)))
  192.   (:result-types tagged-num)
  193.   (:note "safe inline fixnum arithmetic")
  194.   (:generator 4
  195.     (inst tsubcctv r x y)))
  196.  
  197. (define-vop (--c/fixnum fast---c/fixnum=>fixnum)
  198.   (:policy :safe)
  199.   (:results (r :scs (any-reg descriptor-reg)))
  200.   (:result-types tagged-num)
  201.   (:note "safe inline fixnum arithmetic")
  202.   (:generator 3
  203.     (inst tsubcctv r x (fixnum y))))
  204.  
  205. ;;; Shifting
  206.  
  207. (define-vop (fast-ash)
  208.   (:note "inline ASH")
  209.   (:args (number :scs (signed-reg unsigned-reg) :to :save)
  210.      (amount :scs (signed-reg immediate)))
  211.   (:arg-types (:or signed-num unsigned-num) signed-num)
  212.   (:results (result :scs (signed-reg unsigned-reg)))
  213.   (:result-types (:or signed-num unsigned-num))
  214.   (:translate ash)
  215.   (:policy :fast-safe)
  216.   (:temporary (:sc non-descriptor-reg) ndesc)
  217.   (:generator 3
  218.     (sc-case amount
  219.       (signed-reg
  220.        (let ((positive (gen-label))
  221.          (done (gen-label)))
  222.      (inst cmp amount)
  223.      (inst b :ge positive)
  224.      (inst neg ndesc amount)
  225.      (inst cmp ndesc 31)
  226.      (inst b :le done)
  227.      (sc-case number
  228.        (signed-reg (inst sra result number ndesc))
  229.        (unsigned-reg (inst srl result number ndesc)))
  230.      (inst b done)
  231.      (sc-case number
  232.        (signed-reg (inst sra result number 31))
  233.        (unsigned-reg (inst srl result number 31)))
  234.  
  235.      (emit-label positive)
  236.      ;; The result-type assures us that this shift will not overflow.
  237.      (inst sll result number amount)
  238.  
  239.      (emit-label done)))
  240.  
  241.       (immediate
  242.        (let ((amount (tn-value amount)))
  243.      (if (minusp amount)
  244.          (let ((amount (min 31 (- amount))))
  245.            (sc-case number
  246.          (unsigned-reg
  247.           (inst srl result number amount))
  248.          (signed-reg
  249.           (inst sra result number amount))))
  250.          (inst sll result number amount)))))))
  251.  
  252.  
  253.  
  254. (define-vop (signed-byte-32-len)
  255.   (:translate integer-length)
  256.   (:note "inline (signed-byte 32) integer-length")
  257.   (:policy :fast-safe)
  258.   (:args (arg :scs (signed-reg) :target shift))
  259.   (:arg-types signed-num)
  260.   (:results (res :scs (any-reg)))
  261.   (:result-types positive-fixnum)
  262.   (:temporary (:scs (non-descriptor-reg) :from (:argument 0)) shift)
  263.   (:generator 30
  264.     (let ((loop (gen-label))
  265.       (test (gen-label)))
  266.       (inst addcc shift zero-tn arg)
  267.       (inst b :ge test)
  268.       (move res zero-tn)
  269.       (inst b test)
  270.       (inst not shift)
  271.  
  272.       (emit-label loop)
  273.       (inst add res (fixnum 1))
  274.       
  275.       (emit-label test)
  276.       (inst cmp shift)
  277.       (inst b :ne loop)
  278.       (inst srl shift 1))))
  279.  
  280. (define-vop (unsigned-byte-32-count)
  281.   (:translate logcount)
  282.   (:note "inline (unsigned-byte 32) logcount")
  283.   (:policy :fast-safe)
  284.   (:args (arg :scs (unsigned-reg) :target shift))
  285.   (:arg-types unsigned-num)
  286.   (:results (res :scs (any-reg)))
  287.   (:result-types positive-fixnum)
  288.   (:temporary (:scs (non-descriptor-reg) :from (:argument 0)) shift temp)
  289.   (:generator 30
  290.     (let ((loop (gen-label))
  291.       (done (gen-label)))
  292.       (inst addcc shift zero-tn arg)
  293.       (inst b :eq done)
  294.       (move res zero-tn)
  295.  
  296.       (emit-label loop)
  297.       (inst sub temp shift 1)
  298.       (inst andcc shift temp)
  299.       (inst b :ne loop)
  300.       (inst add res (fixnum 1))
  301.  
  302.       (emit-label done))))
  303.  
  304.  
  305. ;;;; Binary conditional VOPs:
  306.  
  307. (define-vop (fast-conditional)
  308.   (:conditional)
  309.   (:info target not-p)
  310.   (:effects)
  311.   (:affected)
  312.   (:policy :fast-safe))
  313.  
  314. (deftype integer-with-a-bite-out (s bite)
  315.   (cond ((eq s '*) 'integer)
  316.     ((and (integerp s) (> s 1))
  317.      (let ((bound (ash 1 (1- s))))
  318.        `(integer ,(- bound) ,(- bound bite 1))))
  319.     (t
  320.      (error "Bad size specified for SIGNED-BYTE type specifier: ~S." s))))
  321.  
  322. (define-vop (fast-conditional/fixnum fast-conditional)
  323.   (:args (x :scs (any-reg zero))
  324.      (y :scs (any-reg zero)))
  325.   (:arg-types tagged-num tagged-num)
  326.   (:note "inline fixnum comparison"))
  327.  
  328. (define-vop (fast-conditional-c/fixnum fast-conditional/fixnum)
  329.   (:args (x :scs (any-reg zero)))
  330.   (:arg-types tagged-num (:constant (signed-byte 11)))
  331.   (:info target not-p y))
  332.  
  333. (define-vop (fast-conditional/signed fast-conditional)
  334.   (:args (x :scs (signed-reg zero))
  335.      (y :scs (signed-reg zero)))
  336.   (:arg-types signed-num signed-num)
  337.   (:note "inline (signed-byte 32) comparison"))
  338.  
  339. (define-vop (fast-conditional-c/signed fast-conditional/signed)
  340.   (:args (x :scs (signed-reg zero)))
  341.   (:arg-types signed-num (:constant (signed-byte 13)))
  342.   (:info target not-p y))
  343.  
  344. (define-vop (fast-conditional/unsigned fast-conditional)
  345.   (:args (x :scs (unsigned-reg zero))
  346.      (y :scs (unsigned-reg zero)))
  347.   (:arg-types unsigned-num unsigned-num)
  348.   (:note "inline (unsigned-byte 32) comparison"))
  349.  
  350. (define-vop (fast-conditional-c/unsigned fast-conditional/unsigned)
  351.   (:args (x :scs (unsigned-reg zero)))
  352.   (:arg-types unsigned-num (:constant (unsigned-byte 12)))
  353.   (:info target not-p y))
  354.  
  355.  
  356. (defmacro define-conditional-vop (tran cond unsigned not-cond not-unsigned)
  357.   `(progn
  358.      ,@(mapcar #'(lambda (suffix cost signed)
  359.            (unless (and (member suffix '(/fixnum -c/fixnum))
  360.                 (eq tran 'eql))
  361.              `(define-vop (,(intern (format nil "~:@(FAST-IF-~A~A~)"
  362.                             tran suffix))
  363.                    ,(intern
  364.                      (format nil "~:@(FAST-CONDITIONAL~A~)"
  365.                          suffix)))
  366.             (:translate ,tran)
  367.             (:generator ,cost
  368.               (inst cmp x
  369.                 ,(if (eq suffix '-c/fixnum) '(fixnum y) 'y))
  370.               (inst b (if not-p
  371.                       ,(if signed not-cond not-unsigned)
  372.                       ,(if signed cond unsigned))
  373.                 target)
  374.               (inst nop)))))
  375.            '(/fixnum -c/fixnum /signed -c/signed /unsigned -c/unsigned)
  376.            '(4 3 6 5 6 5)
  377.            '(t t t t nil nil))))
  378.  
  379. (define-conditional-vop < :lt :ltu :ge :geu)
  380.  
  381. (define-conditional-vop > :gt :gtu :le :leu)
  382.  
  383. (define-conditional-vop eql :eq :eq :ne :ne)
  384.  
  385. ;;; EQL/FIXNUM is funny because the first arg can be of any type, not just a
  386. ;;; known fixnum.
  387.  
  388. ;;; These versions specify a fixnum restriction on their first arg.  We have
  389. ;;; also generic-eql/fixnum VOPs which are the same, but have no restriction on
  390. ;;; the first arg and a higher cost.  The reason for doing this is to prevent
  391. ;;; fixnum specific operations from being used on word integers, spuriously
  392. ;;; consing the argument.
  393. ;;;
  394.  
  395. (define-vop (fast-eql/fixnum fast-conditional)
  396.   (:args (x :scs (any-reg descriptor-reg zero))
  397.      (y :scs (any-reg zero)))
  398.   (:arg-types tagged-num tagged-num)
  399.   (:note "inline fixnum comparison")
  400.   (:translate eql)
  401.   (:generator 4
  402.     (inst cmp x y)
  403.     (inst b (if not-p :ne :eq) target)
  404.     (inst nop)))
  405. ;;;
  406. (define-vop (generic-eql/fixnum fast-eql/fixnum)
  407.   (:arg-types * tagged-num)
  408.   (:variant-cost 7))
  409.  
  410. (define-vop (fast-eql-c/fixnum fast-conditional/fixnum)
  411.   (:args (x :scs (any-reg descriptor-reg zero)))
  412.   (:arg-types tagged-num (:constant (signed-byte 11)))
  413.   (:info target not-p y)
  414.   (:translate eql)
  415.   (:generator 2
  416.     (inst cmp x (fixnum y))
  417.     (inst b (if not-p :ne :eq) target)
  418.     (inst nop)))
  419. ;;;
  420. (define-vop (generic-eql-c/fixnum fast-eql-c/fixnum)
  421.   (:arg-types * (:constant (signed-byte 11)))
  422.   (:variant-cost 6))
  423.  
  424.  
  425. ;;;; 32-bit logical operations
  426.  
  427. (define-vop (merge-bits)
  428.   (:translate merge-bits)
  429.   (:args (shift :scs (signed-reg unsigned-reg))
  430.      (prev :scs (unsigned-reg))
  431.      (next :scs (unsigned-reg)))
  432.   (:arg-types tagged-num unsigned-num unsigned-num)
  433.   (:temporary (:scs (unsigned-reg) :to (:result 0)) temp)
  434.   (:temporary (:scs (unsigned-reg) :to (:result 0) :target result) res)
  435.   (:results (result :scs (unsigned-reg)))
  436.   (:result-types unsigned-num)
  437.   (:policy :fast-safe)
  438.   (:generator 4
  439.     (let ((done (gen-label)))
  440.       (inst cmp shift)
  441.       (inst b :eq done)
  442.       (inst srl res next shift)
  443.       (inst sub temp zero-tn shift)
  444.       (inst sll temp prev temp)
  445.       (inst or res temp)
  446.       (emit-label done)
  447.       (move result res))))
  448.  
  449.  
  450. (define-vop (32bit-logical)
  451.   (:args (x :scs (unsigned-reg zero))
  452.      (y :scs (unsigned-reg zero)))
  453.   (:arg-types unsigned-num unsigned-num)
  454.   (:results (r :scs (unsigned-reg)))
  455.   (:result-types unsigned-num)
  456.   (:policy :fast-safe))
  457.  
  458. (define-vop (32bit-logical-not 32bit-logical)
  459.   (:translate 32bit-logical-not)
  460.   (:args (x :scs (unsigned-reg zero)))
  461.   (:arg-types unsigned-num)
  462.   (:generator 1
  463.     (inst not r x)))
  464.  
  465. (define-vop (32bit-logical-and 32bit-logical)
  466.   (:translate 32bit-logical-and)
  467.   (:generator 1
  468.     (inst and r x y)))
  469.  
  470. (deftransform 32bit-logical-nand ((x y) (* *))
  471.   '(32bit-logical-not (32bit-logical-and x y)))
  472.  
  473. (define-vop (32bit-logical-or 32bit-logical)
  474.   (:translate 32bit-logical-or)
  475.   (:generator 1
  476.     (inst or r x y)))
  477.  
  478. (deftransform 32bit-logical-nor ((x y) (* *))
  479.   '(32bit-logical-not (32bit-logical-or x y)))
  480.  
  481. (define-vop (32bit-logical-xor 32bit-logical)
  482.   (:translate 32bit-logical-xor)
  483.   (:generator 1
  484.     (inst xor r x y)))
  485.  
  486. (define-vop (32bit-logical-eqv 32bit-logical)
  487.   (:translate 32bit-logical-eqv)
  488.   (:generator 1
  489.     (inst xnor r x y)))
  490.  
  491. (define-vop (32bit-logical-orc2 32bit-logical)
  492.   (:translate 32bit-logical-orc2)
  493.   (:generator 1
  494.     (inst orn r x y)))
  495.  
  496. (deftransform 32bit-logical-orc1 ((x y) (* *))
  497.   '(32bit-logical-orc2 y x))
  498.  
  499. (define-vop (32bit-logical-andc2 32bit-logical)
  500.   (:translate 32bit-logical-andc2)
  501.   (:generator 1
  502.     (inst andn r x y)))
  503.  
  504. (deftransform 32bit-logical-andc1 ((x y) (* *))
  505.   '(32bit-logical-andc2 y x))
  506.  
  507.  
  508. (define-vop (shift-towards-someplace)
  509.   (:policy :fast-safe)
  510.   (:args (num :scs (unsigned-reg))
  511.      (amount :scs (signed-reg)))
  512.   (:arg-types unsigned-num tagged-num)
  513.   (:results (r :scs (unsigned-reg)))
  514.   (:result-types unsigned-num))
  515.  
  516. (define-vop (shift-towards-start shift-towards-someplace)
  517.   (:translate shift-towards-start)
  518.   (:note "shift-towards-start")
  519.   (:generator 1
  520.     (inst sll r num amount)))
  521.  
  522. (define-vop (shift-towards-end shift-towards-someplace)
  523.   (:translate shift-towards-end)
  524.   (:note "shift-towards-end")
  525.   (:generator 1
  526.     (inst srl r num amount)))
  527.  
  528.  
  529.  
  530.  
  531. ;;;; Bignum stuff.
  532.  
  533. (define-vop (bignum-length get-header-data)
  534.   (:translate bignum::%bignum-length)
  535.   (:policy :fast-safe))
  536.  
  537. (define-vop (bignum-set-length set-header-data)
  538.   (:translate bignum::%bignum-set-length)
  539.   (:policy :fast-safe))
  540.  
  541. (define-vop (bignum-ref word-index-ref)
  542.   (:variant vm:bignum-digits-offset vm:other-pointer-type)
  543.   (:translate bignum::%bignum-ref)
  544.   (:results (value :scs (unsigned-reg)))
  545.   (:result-types unsigned-num))
  546.  
  547. (define-vop (bignum-set word-index-set)
  548.   (:variant vm:bignum-digits-offset vm:other-pointer-type)
  549.   (:translate bignum::%bignum-set)
  550.   (:args (object :scs (descriptor-reg))
  551.      (index :scs (any-reg immediate zero))
  552.      (value :scs (unsigned-reg)))
  553.   (:arg-types t positive-fixnum unsigned-num)
  554.   (:results (result :scs (unsigned-reg)))
  555.   (:result-types unsigned-num))
  556.  
  557. (define-vop (digit-0-or-plus)
  558.   (:translate bignum::%digit-0-or-plusp)
  559.   (:policy :fast-safe)
  560.   (:args (digit :scs (unsigned-reg)))
  561.   (:arg-types unsigned-num)
  562.   (:results (result :scs (descriptor-reg)))
  563.   (:generator 3
  564.     (let ((done (gen-label)))
  565.       (inst cmp digit)
  566.       (inst b :lt done)
  567.       (move result null-tn)
  568.       (load-symbol result t)
  569.       (emit-label done))))
  570.  
  571. (define-vop (add-w/carry)
  572.   (:translate bignum::%add-with-carry)
  573.   (:policy :fast-safe)
  574.   (:args (a :scs (unsigned-reg))
  575.      (b :scs (unsigned-reg))
  576.      (c :scs (any-reg)))
  577.   (:arg-types unsigned-num unsigned-num positive-fixnum)
  578.   (:results (result :scs (unsigned-reg))
  579.         (carry :scs (unsigned-reg)))
  580.   (:result-types unsigned-num positive-fixnum)
  581.   (:generator 3
  582.     (inst addcc zero-tn c -1)
  583.     (inst addxcc result a b)
  584.     (inst addx carry zero-tn zero-tn)))
  585.  
  586. (define-vop (sub-w/borrow)
  587.   (:translate bignum::%subtract-with-borrow)
  588.   (:policy :fast-safe)
  589.   (:args (a :scs (unsigned-reg))
  590.      (b :scs (unsigned-reg))
  591.      (c :scs (any-reg)))
  592.   (:arg-types unsigned-num unsigned-num positive-fixnum)
  593.   (:results (result :scs (unsigned-reg))
  594.         (borrow :scs (unsigned-reg)))
  595.   (:result-types unsigned-num positive-fixnum)
  596.   (:generator 4
  597.     (inst subcc zero-tn c 1)
  598.     (inst subxcc result a b)
  599.     (inst addx borrow zero-tn zero-tn)
  600.     (inst xor borrow 1)))
  601.  
  602. ;;; EMIT-MULTIPLY -- This is used both for bignum stuff and in assembly
  603. ;;; routines.
  604. ;;; 
  605. (defun emit-multiply (multiplier multiplicand result-high result-low)
  606.   "Emit code to multiply MULTIPLIER with MULTIPLICAND, putting the result
  607.   in RESULT-HIGH and RESULT-LOW.  KIND is either :signed or :unsigned.
  608.   Note: the lifetimes of MULTIPLICAND and RESULT-HIGH overlap."
  609.   (declare (type tn multiplier result-high result-low)
  610.        (type (or tn (signed-byte 13)) multiplicand))
  611.   (let ((label (gen-label)))
  612.     (inst wry multiplier)
  613.     (inst andcc result-high zero-tn)
  614.     ;; Note: we can't use the Y register until three insts after it's written.
  615.     (inst nop)
  616.     (inst nop)
  617.     (dotimes (i 32)
  618.       (inst mulscc result-high multiplicand))
  619.     (inst mulscc result-high zero-tn)
  620.     (inst cmp multiplicand)
  621.     (inst b :ge label)
  622.     (inst nop)
  623.     (inst add result-high multiplier)
  624.     (emit-label label)
  625.     (inst rdy result-low)))
  626.  
  627. (define-vop (bignum-mult-and-add-3-arg)
  628.   (:translate bignum::%multiply-and-add)
  629.   (:policy :fast-safe)
  630.   (:args (x :scs (unsigned-reg) :to (:eval 1))
  631.      (y :scs (unsigned-reg) :to (:eval 1))
  632.      (carry-in :scs (unsigned-reg) :to (:eval 2)))
  633.   (:arg-types unsigned-num unsigned-num unsigned-num)
  634.   (:results (hi :scs (unsigned-reg) :from (:eval 0))
  635.         (lo :scs (unsigned-reg) :from (:eval 1)))
  636.   (:result-types unsigned-num unsigned-num)
  637.   (:generator 40
  638.     (emit-multiply x y hi lo)
  639.     (inst addcc lo carry-in)
  640.     (inst addx hi zero-tn)))
  641.  
  642. (define-vop (bignum-mult-and-add-4-arg)
  643.   (:translate bignum::%multiply-and-add)
  644.   (:policy :fast-safe)
  645.   (:args (x :scs (unsigned-reg) :to (:eval 1))
  646.      (y :scs (unsigned-reg) :to (:eval 1))
  647.      (prev :scs (unsigned-reg) :to (:eval 2))
  648.      (carry-in :scs (unsigned-reg) :to (:eval 2)))
  649.   (:arg-types unsigned-num unsigned-num unsigned-num unsigned-num)
  650.   (:results (hi :scs (unsigned-reg) :from (:eval 0))
  651.         (lo :scs (unsigned-reg) :from (:eval 1)))
  652.   (:result-types unsigned-num unsigned-num)
  653.   (:generator 40
  654.     (emit-multiply x y hi lo)
  655.     (inst addcc lo carry-in)
  656.     (inst addx hi zero-tn)
  657.     (inst addcc lo prev)
  658.     (inst addx hi zero-tn)))
  659.  
  660. (define-vop (bignum-mult)
  661.   (:translate bignum::%multiply)
  662.   (:policy :fast-safe)
  663.   (:args (x :scs (unsigned-reg) :to (:result 1))
  664.      (y :scs (unsigned-reg) :to (:result 1)))
  665.   (:arg-types unsigned-num unsigned-num)
  666.   (:results (hi :scs (unsigned-reg))
  667.         (lo :scs (unsigned-reg)))
  668.   (:result-types unsigned-num unsigned-num)
  669.   (:generator 40
  670.     (emit-multiply x y hi lo)))
  671.  
  672. (define-vop (bignum-lognot)
  673.   (:translate bignum::%lognot)
  674.   (:policy :fast-safe)
  675.   (:args (x :scs (unsigned-reg)))
  676.   (:arg-types unsigned-num)
  677.   (:results (r :scs (unsigned-reg)))
  678.   (:result-types unsigned-num)
  679.   (:generator 1
  680.     (inst not r x)))
  681.  
  682. (define-vop (fixnum-to-digit)
  683.   (:translate bignum::%fixnum-to-digit)
  684.   (:policy :fast-safe)
  685.   (:args (fixnum :scs (any-reg)))
  686.   (:arg-types tagged-num)
  687.   (:results (digit :scs (unsigned-reg)))
  688.   (:result-types unsigned-num)
  689.   (:generator 1
  690.     (inst sra digit fixnum 2)))
  691.  
  692. (define-vop (bignum-floor)
  693.   (:translate bignum::%floor)
  694.   (:policy :fast-safe)
  695.   (:args (div-high :scs (unsigned-reg) :target rem)
  696.      (div-low :scs (unsigned-reg) :target quo)
  697.      (divisor :scs (unsigned-reg)))
  698.   (:arg-types unsigned-num unsigned-num unsigned-num)
  699.   (:results (quo :scs (unsigned-reg) :from (:argument 1))
  700.         (rem :scs (unsigned-reg) :from (:argument 0)))
  701.   (:result-types unsigned-num unsigned-num)
  702.   (:generator 300
  703.     (move rem div-high)
  704.     (move quo div-low)
  705.     (dotimes (i 33)
  706.       (let ((label (gen-label)))
  707.     (inst cmp rem divisor)
  708.     (inst b :ltu label)
  709.     (inst addxcc quo quo)
  710.     (inst sub rem divisor)
  711.     (emit-label label)
  712.     (unless (= i 32)
  713.       (inst addx rem rem))))
  714.     (inst not quo)))
  715.  
  716. (define-vop (signify-digit)
  717.   (:translate bignum::%fixnum-digit-with-correct-sign)
  718.   (:policy :fast-safe)
  719.   (:args (digit :scs (unsigned-reg) :target res))
  720.   (:arg-types unsigned-num)
  721.   (:results (res :scs (any-reg signed-reg)))
  722.   (:result-types signed-num)
  723.   (:generator 1
  724.     (sc-case res
  725.       (any-reg
  726.        (inst sll res digit 2))
  727.       (signed-reg
  728.        (move res digit)))))
  729.  
  730.  
  731. (define-vop (digit-ashr)
  732.   (:translate bignum::%ashr)
  733.   (:policy :fast-safe)
  734.   (:args (digit :scs (unsigned-reg))
  735.      (count :scs (unsigned-reg)))
  736.   (:arg-types unsigned-num positive-fixnum)
  737.   (:results (result :scs (unsigned-reg)))
  738.   (:result-types unsigned-num)
  739.   (:generator 1
  740.     (inst sra result digit count)))
  741.  
  742. (define-vop (digit-lshr digit-ashr)
  743.   (:translate bignum::%digit-logical-shift-right)
  744.   (:generator 1
  745.     (inst srl result digit count)))
  746.  
  747. (define-vop (digit-ashl digit-ashr)
  748.   (:translate bignum::%ashl)
  749.   (:generator 1
  750.     (inst sll result digit count)))
  751.  
  752.  
  753. ;;;; Static functions.
  754.  
  755. (define-static-function two-arg-gcd (x y) :translate gcd)
  756. (define-static-function two-arg-lcm (x y) :translate lcm)
  757.  
  758. (define-static-function two-arg-+ (x y) :translate +)
  759. (define-static-function two-arg-- (x y) :translate -)
  760. (define-static-function two-arg-* (x y) :translate *)
  761. (define-static-function two-arg-/ (x y) :translate /)
  762.  
  763. (define-static-function two-arg-< (x y) :translate <)
  764. (define-static-function two-arg-<= (x y) :translate <=)
  765. (define-static-function two-arg-> (x y) :translate >)
  766. (define-static-function two-arg->= (x y) :translate >=)
  767. (define-static-function two-arg-= (x y) :translate =)
  768. (define-static-function two-arg-/= (x y) :translate /=)
  769.  
  770. (define-static-function %negate (x) :translate %negate)
  771.  
  772. (define-static-function two-arg-and (x y) :translate logand)
  773. (define-static-function two-arg-ior (x y) :translate logior)
  774. (define-static-function two-arg-xor (x y) :translate logxor)
  775.